/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 *
 * $Id: BehaviourServer.hpp,v 1.5 2009-05-13 07:18:16 amaula Exp $
 *
 * \file
 * \brief MaCI - Behaviour Interface Server module header
 * \author Matthieu Myrsky <matthieu.myrsky@tkk.fi>
 */
#ifndef _MACI_BEHAVIOURSERVER_HPP_
#define _MACI_BEAHVIOURSERVER_HPP_
#include "MaCI.hpp"
#include "thread.hpp"
#include "BehaviourData.hpp"
#include <vector>

namespace gimi {
  class GIMIMessage;
}

namespace MaCI {
  namespace Behaviour {

    /** MaCI - BehaviourServer Interface.
     *
     * This class defines a Server module to be used with the 
     * MaCI Behaviour interface.
     */
    class CBehaviourServer : public CMaCI, 
                             private gim::CThread,
                             private gim::CSync
    {
    public:
      /** Constructor.
       * 
       * Constructor of the BehaviourServer. This requires;
       * a pointer to Initialized and connected GIMI, minor
       * number of this interface (Used as GIMI minor number)
       *
       * @param[in] aMaCICtrlServerPtr Pointer to GIMI used for communication
       * @param[in] aInterfaceMinor Interface minor number. Usually
       * used to indicate the instance of devices of same
       * type.
       * @param[in] aDescription User provided description about
       * service. This description will be appended after text
       * 'MaCI-RangingServer; ' in the GIMI service description
       * field.
       */
      CBehaviourServer(MaCICtrl::CMaCICtrlServer *aMaCICtrlServerPtr, 
                     const int aInterfaceMinor,
                     const std::string &aDescription = "");
 
      
      /** Destructor.
       *
       * Cleans up the class. Calls the Close() function to verify
       * that all derived-class things are closed.
       *
       */
      ~CBehaviourServer();
      
      /**
       * Sends behaviour control value event to service subscribers.
       * The CBehaviourData must contain  KCommandBehaviourControlEvent-Command
       * and TBehaviourControl-structure or TBehaviourControlSpeed-structure
       *
       * @param[in] aData         CBehaviourData container containing
       *                          TBehaviourControl-structure and the command
       */
      bool SendBehaviourControlEvent(const CBehaviourData &aData);

      bool SendBehaviourStateEvent(bool aState);
      /**
       * Sets the type of the behaviour. The behaviour type has to be set
       * BEFORE opening the device!
       *
       * There are three types of behaviours:
       * 1.Normal
       *   Normal behaviours commands are used when protective behaviours
       *   don't give their commands
       * 2.aiding
       *   Aiding behaviours command when the the robot is moving.
       * 3.protective
       *   Protective behaviours overrides all other behaviour-type commands
       *
       * @param[in] aType        Behaviour type to Set.
       */
      void SetBehaviourType(EBehaviourType aType);

      /** Wait for command from Client.
       *
       * This function waits for a Command to arrive from client, and returns it
       * in the provided reference to CBehaviourData.
       * The function guarantees that the data element contains a TCommand,
       * but the user must check whether all accompanying elements required for
       * the specified command exist.
       *
       * @param[out] aData      Reference to CBehaviourData to be filled.
       * @param[in] aTimeout_ms Time to wait for a command (milliseconds)
       * @return                'KMaCIOK'  when succesfully received
       *                        a new command. KMaCITimeout when operation
       *                        timed out before a command was received.
       *                        Other errors returned when appropriate.
       *                        (See the MaCI::EMaCIError for description)
       */
      EMaCIError WaitCommand(CBehaviourData &aData, 
                             const unsigned int aTimeout_ms);

    protected:
      /** Open device.
       *
       * Opens the device, basicly registers device to GIMI.
       *  
       * @return                Returns a value of type EMaCIError. 
       *                        
       * \see EMaCIError
       */
      EMaCIError DoOpen(void);


      /** Close device.
       *
       * Closes the device. Closes all GIMI registrations and queues.
       *
       * @return                Returns a value of type EMaCIError.
       *
       * \see EMaCIError
       */
      EMaCIError DoClose(void);


     

    private:
      int ThreadFunction(const int aThreadNumber); ///< Incoming data handler function
      int ProcessMessage(const gimi::GIMIMessage &msg); ///< Incoming data processor function
      bool iServerActive; ///< Is the server active? - flag
      bool iBehaviourTypeSet;
      std::string iServiceDescription; ///< Service description.
      CBehaviourData iBehaviourData;
      EBehaviourType iBehaviourType;
    };
  }
}

#endif
